package com.gome.axwl.aoc.facade.impl;

import com.cloudcache.client.cluster.base.CloudCacheClient;
import com.github.pagehelper.PageInfo;
import com.gome.axwl.aoc.common.util.ErrorCode;
import com.gome.axwl.aoc.entity.dto.PageResultDto;
import com.gome.axwl.aoc.entity.enums.BusinessEnum;
import com.gome.axwl.aoc.entity.exception.ZQException;
import com.gome.axwl.aoc.entity.po.*;
import com.gome.axwl.aoc.entity.zq.ZQBaseResult;
import com.gome.axwl.aoc.entity.zq.ZQContractImage;
import com.gome.axwl.aoc.entity.zq.ZQContractPdf;
import com.gome.axwl.aoc.entity.zq.ZQEmptyContract;
import com.gome.axwl.aoc.facade.ContractFacade;
import com.gome.axwl.aoc.facade.SmsSendFacade;
import com.gome.axwl.aoc.facade.util.Base64Utils;
import com.gome.axwl.aoc.facade.util.DownloadFileUtil;
import com.gome.axwl.aoc.facade.util.ZQCheckResponseUtil;
import com.gome.axwl.aoc.facade.util.ZQRequestUtil;
import com.gome.axwl.aoc.service.*;
import com.gome.common.utils.StringUtil;
import com.gome.commons.core.ResultData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by wanglongyu on 2018/7/13.
 */
@Service
public class ContractFacadeImpl implements ContractFacade{
    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private final static String CONTRACT_REDIS_KEY = "CONTRACT_NO";
    @Autowired
    private ContractService contractService;
    @Autowired
    private ContractTemplateService contractTemplateService;
    @Autowired
    private EmptyContractService emptyContractService;
    @Autowired
    private ZQRequestUtil zqRequestUtil;
    @Autowired
    private CloudCacheClient redisCache;
    @Autowired
    private FileUploadRecordService fileUploadRecordService;
    @Autowired
    private SmsSendFacade smsSendFacade;
    @Autowired
    private CsApplyinfoService csApplyinfoService;
    @Value("${carrierSettle.messageForCarrier}")
    private String messageForCarrier;
    @Override
    public PageResultDto<ContractPo> queryContract(String contractName, String contractNo,
                                                   String carrierPhone,String carrierName,Integer status,
                                                   Date startTime, Date endTime, Integer pageNum, Integer pageSize) {
        PageInfo<ContractPo> pageInfo = contractService.queryContract(contractName,contractNo,carrierPhone,carrierName,status, startTime, endTime, pageNum, pageSize);
        PageResultDto<ContractPo> pageResultDto=new PageResultDto<>();
        pageResultDto.setPageNum(pageInfo.getPageNum());
        pageResultDto.setPageSize(pageInfo.getPageSize());
        pageResultDto.setTotal(pageInfo.getTotal());
        pageResultDto.setPageCount(pageInfo.getPages());
        pageResultDto.setData(pageInfo.getList());
        return pageResultDto;
    }

    @Override
    public List<String> getDetail(String contractNo) throws ZQException {
        ContractPo contractPo = contractService.queryByContractNo(contractNo);
        if (contractPo!=null &&3==contractPo.getStatus()){
            ZQContractImage result = zqRequestUtil.downloadContractImg(contractNo);
            ZQCheckResponseUtil.validZQResponse(result);
            return result.getImgList();
        }
       return null;
    }

    @Override
    public String download(String contractNo) throws ZQException {
        ZQContractPdf result = zqRequestUtil.downloadContract(contractNo);
        ZQCheckResponseUtil.validZQResponse(result);
        return result.getPdfUrl();
    }

    @Override
    public Integer completionContract(String contractNo) throws ZQException {
        ZQBaseResult result = zqRequestUtil.completionContract(contractNo);
        ZQCheckResponseUtil.validZQResponse(result);
        return 1;
    }

    @Override
    public ResultData remindCarrier(String contractPhone, String carrierName) {
        return smsSendFacade.sendSmsWithAxwlConfig(contractPhone,String.format(messageForCarrier,carrierName));
    }

    @Override
    public Integer signCheckMark(String no, String signers) throws ZQException {
        if(valid(no,signers)){
            throw new ZQException(ErrorCode.PARAM_IS_NULL,ErrorCode.PARAM_IS_NULL_MSG);
        }
        ZQBaseResult result = zqRequestUtil.signCheckMark(no, signers);
        ZQCheckResponseUtil.validZQResponse(result);
        return 1;
    }

    @Override
    public Integer signAuto(String no, String signers) throws ZQException {
        if(valid(no,signers)){
            throw new ZQException(ErrorCode.PARAM_IS_NULL,ErrorCode.PARAM_IS_NULL_MSG);
        }
        ZQBaseResult result = zqRequestUtil.signAuto(no, signers);
        ZQCheckResponseUtil.validZQResponse(result);
        return 1;
    }

    @Override
    public EmptyContractResponse getEmptyContract(Integer applyInfoId) throws ZQException {
        EmptyContractPo emptyMsg = emptyContractService.queryByApplyInfoId(applyInfoId);
        EmptyContractResponse response = new EmptyContractResponse();
        if(emptyMsg != null){
            ZQContractImage zqResult = zqRequestUtil.downloadEmptyContractImg(emptyMsg.getEmptyContractNo());
            ZQCheckResponseUtil.validZQResponse(zqResult);
            response.setDetail(emptyMsg.getEmptyContractJson());
            response.setImgs(zqResult.getImgList());
        }
        return response;
    }

    @Override
    public Integer entpReg(String userCode, String name, String certificate, String address, String contact, String phone) throws ZQException {
        if(valid(userCode, name, certificate, address, contact, phone)){
            throw new ZQException(ErrorCode.PARAM_IS_NULL,ErrorCode.PARAM_IS_NULL_MSG);
        }
        ZQBaseResult result = zqRequestUtil.entpReg(userCode, name, certificate, address, contact, phone);
        ZQCheckResponseUtil.validZQResponse(result);
        return 1;
    }

    @Override
    public Integer personReg(String userCode, String name, String idCardNo, String phone) throws ZQException {
        if(valid(userCode,name,idCardNo,phone)){
            throw new ZQException(ErrorCode.PARAM_IS_NULL,ErrorCode.PARAM_IS_NULL_MSG);
        }
        ZQBaseResult result = zqRequestUtil.personReg(userCode,name,idCardNo,phone);
        ZQCheckResponseUtil.validZQResponse(result);
        return 1;
    }

    @Override
    public Integer personUpdate(String userCode, String name, String idCardNo, String phone) throws ZQException {
        if(valid(userCode,name,idCardNo,phone)){
            throw new ZQException(ErrorCode.PARAM_IS_NULL,ErrorCode.PARAM_IS_NULL_MSG);
        }
        ZQBaseResult result = zqRequestUtil.personReg(userCode,name,idCardNo,phone);
        ZQCheckResponseUtil.validZQResponse(result);
        return 1;
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String buildEmptyContract(BuildEmptyContractRequest request) throws ZQException {
        /**Step 1.生成合同编码*/
        String contractNo = getContractNo();
        /*Step 2.循环获取附件，并调用众签生成空白合同模板。*/
        List<FileUploadRecordPo> files = fileUploadRecordService.queryByFileScenesAndSencesId(BusinessEnum.CARRIER_SETTLE_FILE_TYPE_ATTACHMENT.getItemCode()
                , request.getApplyInfoId());
        List<String> fileUrls = new ArrayList<>();
        for (FileUploadRecordPo fi: files) {
            fileUrls.add(fi.getFileUrl());
        }
        ZQEmptyContract zqEmptyContract = buildContractByZQ(request.getTemplateNo(), request.getContractName(), fileUrls);
        /*Step 3.给用户颁发数字证书。*/
        Integer certificate = null;
        if(request.getStatus() != null && request.getStatus() == 2){//企业用户
            certificate = entpReg(request.getCarrierCode(), request.getCompanyName(),
               request.getCertificate(), request.getAddress(), request.getCorporationName(), request.getCarrierPhone());
        }
        if(request.getStatus() != null && request.getStatus() == 1){//个人用户
            certificate = personReg(request.getCarrierCode(),request.getCarrierName(),request.getIdentity(),request.getCarrierPhone());
        }
        if(certificate == null || certificate == 0){
            throw new ZQException(ErrorCode.CERTIFICATE_FAILD,ErrorCode.CERTIFICATE_FAILD_MSG);
        }
        /*Step 4.保存合同信息到数据库。*/
        ContractPo contractPo = new ContractPo();
        contractPo.setApplyInfoId(request.getApplyInfoId());
        contractPo.setTemplateNo(request.getTemplateNo());
        contractPo.setContractName(request.getContractName());
        contractPo.setContractNo(contractNo);
        contractPo.setCarrierName(request.getCarrierName());
        contractPo.setCarrierPhone(request.getCarrierPhone());
        contractPo.setAuditName(request.getAuditName());
        contractPo.setCorporationName(request.getCorporationName());
        contractPo.setCarrierCode(request.getCarrierCode());
        contractPo.setAuditCode(request.getAuditCode());
        Integer addRe = contractService.addContract(contractPo);
        if(addRe != 1){
            throw new ZQException(ErrorCode.APPLY_INFO_ID_ERROR,ErrorCode.APPLY_INFO_ID_ERROR_MSG);
        }
        /*Step 5.保存空白合同模板信息*/
        EmptyContractPo emptyContractPo = new EmptyContractPo();
        emptyContractPo.setApplyInfoId(request.getApplyInfoId());
        emptyContractPo.setEmptyContractNo(zqEmptyContract.getT_no());
        emptyContractPo.setEmptyContractJson(zqEmptyContract.getJson_val());
        emptyContractPo.setCreateTime(new Date());
        Integer re = emptyContractService.addEmptyContract(emptyContractPo);
        if(re != 1){
            throw new ZQException(ErrorCode.APPLY_INFO_ID_ERROR,ErrorCode.APPLY_INFO_ID_ERROR_MSG);
        }
        return contractNo;
    }

    /***
     * 根据附件个数 循环调用众签 生成模板
     * @param templateNo
     * @param contractName
     * @param fileUrls
     * @return
     * @throws ZQException
     */
    private ZQEmptyContract buildContractByZQ(String templateNo, String contractName, List<String> fileUrls) throws ZQException {
        ZQEmptyContract newTemp = new ZQEmptyContract();
        String newTempNo = templateNo;
        for (int i = 0;i < fileUrls.size();i++) {
            String fileUrl = fileUrls.get(i);
            /**获取文件输入流*/
            InputStream in = DownloadFileUtil.getFile(fileUrl);
            byte[] inputByte;
            String base64 = "";
            if(i > 0){
                newTempNo = newTemp.getT_no();
            }
            try {
                inputByte = Base64Utils.input2byte(in);
                base64 = Base64Utils.encode(inputByte);
                newTemp = zqRequestUtil.updateTemplate(base64, contractName, newTempNo);
                ZQCheckResponseUtil.validZQResponse(newTemp);
            } catch (IOException e) {
                logger.info("第[ {} ]次，文件解析失败",i);
                throw new ZQException(ErrorCode.READ_FILE_ERROR,ErrorCode.READ_FILE_ERROR_MSG);
            }catch (ZQException e) {
                logger.info("第[ {} ]次，调用众签创建模板失败",i);
                throw new ZQException(e.getCode(),e.getMessage());
            }catch (Exception e) {
                logger.info("第[ {} ]次，获取文件base64失败",i);
                throw new ZQException(ErrorCode.READ_FILE_ERROR,ErrorCode.READ_FILE_ERROR_MSG);
            }
        }
        return newTemp;
    }

    /***
     * 根据redis 获取合同编码
     * @return
     */
    private String getContractNo() {
    /*Step 1 获取redis中合同编码编号*/
        String redisKeyString = redisCache.get(CONTRACT_REDIS_KEY);
        Integer redisKey;
        //第一次编码不存在就默认为1，否则就+1
        if(StringUtil.isBlank(redisKeyString)){
            redisKey = 1;
        }else {
            redisKey = Integer.valueOf(redisKeyString) + 1;
        }
        redisCache.set(CONTRACT_REDIS_KEY,redisKey.toString());
        /*Step 2 根据redis中编号，生成合同编号*/
        String format = "%08d";
        return String.format(format,redisKey);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer signByCarrier(Integer applyInfoId, String signName, String signJson) throws ZQException {
        String signPerson = getSignPerson(applyInfoId, signName);
        //保存json到空白合同
        Integer jsonResult = emptyContractService.updateJson(signJson,applyInfoId,new Date());
        if(jsonResult != 1){
            throw new ZQException(ErrorCode.APPLY_INFO_ID_ERROR,ErrorCode.APPLY_INFO_ID_ERROR_MSG);
        }
        Integer signResult = contractService.sign(signPerson,applyInfoId,new Date());
        if(signResult != 1){
            throw new ZQException(ErrorCode.APPLY_INFO_ID_ERROR,ErrorCode.APPLY_INFO_ID_ERROR_MSG);
        }
        ContractTemplatePo contractTemplate = contractTemplateService.selectByApplyInfoId(applyInfoId);
        if(contractTemplate == null){
            throw new ZQException(ErrorCode.APPLY_INFO_ID_ERROR,ErrorCode.APPLY_INFO_ID_ERROR_MSG);
        }
        if(contractTemplate.getSignWay() == 1){
           signContract(applyInfoId,1,null);
        }
        //修改入驻申请单状态 yinyuxin
        CsApplyInfoPo csApplyInfoPo=csApplyinfoService.queryById(applyInfoId);
        if (csApplyInfoPo==null){
            throw new RuntimeException("入驻单查询为null,服务商签署失败");
        }
        if (contractTemplate.getSignWay()==1){
            //自动签署
            csApplyInfoPo.setApprovalStatus(BusinessEnum.CARRIER_SETTLE_APPROVAL_STATUS_SS.getItemCode());
        }else{
            //手动签署
            csApplyInfoPo.setApprovalStatus(BusinessEnum.CARRIER_SETTLE_APPROVAL_STATUS_SPED.getItemCode());
        }
        csApplyinfoService.update(csApplyInfoPo);
        return 1;
    }

    private String getSignPerson(Integer applyInfoId, String signName) throws ZQException {
        ContractPo contract = contractService.getByApplyInfoId(applyInfoId);
        if(contract == null){
            throw new ZQException(ErrorCode.APPLY_INFO_ID_ERROR,ErrorCode.APPLY_INFO_ID_ERROR_MSG);
        }
        String signPerson = contract.getSignPerson();
        if(StringUtil.isBlank(signPerson)){
            signPerson = signName;
        }else {
            signPerson = signPerson + "," + signName;
        }
        return signPerson;
    }
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Integer signByAoc(Integer applyInfoId, Integer auditStatus, String signName, String unpassReason) throws ZQException {
        if(auditStatus == 0){//审核未通过
            //更新合同表
            Integer con = contractService.unpass(unpassReason,auditStatus,applyInfoId,new Date());
            if(con != 1){
                throw new ZQException(ErrorCode.APPLY_INFO_ID_ERROR,ErrorCode.APPLY_INFO_ID_ERROR_MSG);
            }
            //更新空白合同表
            return emptyContractService.updateStatus(applyInfoId,1,new Date());
        }
        if(auditStatus ==1){//审核通过
            signContract(applyInfoId, auditStatus, signName);
        }
        return 1;
    }

    private void signContract(Integer applyInfoId, Integer auditStatus, String signName) throws ZQException {
        //获取空白合同
        EmptyContractPo emptyContract = emptyContractService.queryByApplyInfoId(applyInfoId);
        if(emptyContract == null){
            throw new ZQException(ErrorCode.APPLY_INFO_ID_ERROR,ErrorCode.APPLY_INFO_ID_ERROR_MSG);
        }
        //获取合同信息
        ContractPo contract = contractService.getByApplyInfoId(applyInfoId);
        if(contract == null){
            throw new ZQException(ErrorCode.APPLY_INFO_ID_ERROR,ErrorCode.APPLY_INFO_ID_ERROR_MSG);
        }
        if(StringUtil.isBlank(signName)){
            signName = contract.getAuditName();
        }
        //拼接签署人
        String signPerson = getSignPerson(applyInfoId, signName);
        //调用众签根据模板生成合同
        ZQBaseResult response = zqRequestUtil.createContract(contract.getContractNo(),
                contract.getContractName(), emptyContract.getEmptyContractNo(), emptyContract.getEmptyContractJson());
        ZQCheckResponseUtil.validZQResponse(response);
        //获取签署人id 多个,号隔开
        String signers = contract.getAuditCode() + "," + contract.getCarrierCode();
        //自动签署
        ZQBaseResult signAutoResponse = zqRequestUtil.signAuto(contract.getContractNo(), signers);
        ZQCheckResponseUtil.validZQResponse(signAutoResponse);
        //骑缝章签署
        ZQBaseResult markResponse = zqRequestUtil.signCheckMark(contract.getContractNo(), signers);
        ZQCheckResponseUtil.validZQResponse(markResponse);
        //调用众签合同生效接口
        ZQBaseResult completionResult = zqRequestUtil.completionContract(contract.getContractNo());
        ZQCheckResponseUtil.validZQResponse(completionResult);
        //更新合同表
        Integer passRe = contractService.pass(signPerson,auditStatus,applyInfoId,new Date());
        if(passRe != 1){
            throw new ZQException(ErrorCode.APPLY_INFO_ID_ERROR,ErrorCode.APPLY_INFO_ID_ERROR_MSG);
        }
        //更新空白合同表
        Integer emptyRe = emptyContractService.updateStatus(applyInfoId,3,new Date());
        if(emptyRe != 1){
            throw new ZQException(ErrorCode.APPLY_INFO_ID_ERROR,ErrorCode.APPLY_INFO_ID_ERROR_MSG);
        }
    }

    /***
     * 验证所有参数不能为空
     * @param param 参数均为String
     * @return
     */
    private boolean valid(String... param) {
        for (int i = 0;i < param.length;i++) {
            if (StringUtil.isBlank(param[i])) {
                return true;
            }
        }
        return false;
    }

}
